package de.cms.kff.dao;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;


import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import de.cms.kff.dto.MitarbeiterVerleihDTO;
import de.cms.kff.dto.VerleihDTO;
import de.cms.kff.model.Auto;
import de.cms.kff.model.Verleih;
import de.cms.kff.model.Mitarbeiter;


/**
 * @author josef@dr-schneeberger.de
 */
public class VerleihDao extends HibernateDaoSupport {
	SimpleDateFormat deutschesDatumsFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");

	/**
	 * <p>returns all Fahrt objects, which are not yet termiated, i.e. which have a ankunft property == null.
	 * All the results are returned as FahrtPersonenDTO objects.</p>
	 * <p>In order to access lazy loaded properties, a HibernateCallback is used.</p>
	 * @return A sorted set of FahrtPersonenDTO objects
	 * @see http://static.springframework.org/spring/docs/2.5.x/reference/orm.html#orm-hibernate-template
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Set<VerleihDTO> findNichtBeendetDTO() {
		HibernateTemplate template = getHibernateTemplate();
		return (Set<VerleihDTO>) template.execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(Verleih.class);
				criteria.add(Restrictions.isNull("bis"));
				List<Verleih> alleVerleihe = criteria.list();
				return createDtoSet(alleVerleihe);
			}
		});
	}

	/**
	 * <p>returns all Fahrt objects as FahrtPersonenDTO objects.</p>
	 * <p>In order to access lazy loaded properties of those, a HibernateCallback is used.</p>
	 * @return A sorted set of FahrtPersonenDTO objects
	 * @see http://static.springframework.org/spring/docs/2.5.x/reference/orm.html#orm-hibernate-template
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Set<VerleihDTO> findAllDTO() {
		HibernateTemplate template = getHibernateTemplate();
		return (Set<VerleihDTO>) template.execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(Verleih.class);
				List<Verleih> alleFahrten = criteria.list();
				return createDtoSet(alleFahrten);
			}
		});
	}

	/**
	 * Private utility function
	 * @param fahrten a List of persistent Fahrt objects
	 * @return a Set of FahrtPersonenDTO objects
	 */
	private Set<VerleihDTO> createDtoSet(List<Verleih> fahrten) {
		Set<VerleihDTO> results = new TreeSet<VerleihDTO>();
		for (Verleih f : fahrten) {
			Date bis = f.getBis();
			Date von = f.getVon();
			results.add(new VerleihDTO(
					f.getId(),
					f.getCreated(),
					f.getAuto().getTyp(),
					f.getAuto().getKennzeichen(),
					(von == null ? "" : deutschesDatumsFormat.format(von)),
					(bis == null ? "" : deutschesDatumsFormat.format(bis)),
					f.getMitarbeiter().getVorname(),
					f.getMitarbeiter().getNachname(),
					f.getKilometerstand()));
					
		}
	
		
		return results;
	}

	/**
	 * Private utility function
	 * @param rudererSet a Set of Person objects
	 * @return a String of the names of those Person objects
	 
	private String mannschaftToString(Set<Mitarbeiter> rudererSet) {
		String mannschaft = "";
		String trenner = "";
		for (Mitarbeiter ruderer : rudererSet) {
			mannschaft = mannschaft + trenner + ruderer.getVorname() + " "
					+ ruderer.getNachname();
			trenner = ", ";
		}
		return mannschaft;
	} */

	/**
	 * @return all Fahrt objects in the database.
	 */
	@SuppressWarnings("unchecked")
	public List<Verleih> findAll() {
		HibernateTemplate template = getHibernateTemplate();
		@SuppressWarnings("rawtypes")
		List alleFahrten = template.loadAll(Verleih.class);
		return (List<Verleih>) alleFahrten;
	}

	/**
	 * Starts a trip specifying a Boot id and a set of Person ids.
	 * @param bootId
	 * @param sitz
	 * @throws DaoException 
	 */
	public void verleihe(int autoId, int mitarbeiterId, int kilometerstand) throws DaoException {
		HibernateTemplate template = getHibernateTemplate();
		Auto a = (Auto) template.get(Auto.class, autoId);
		Mitarbeiter m = (Mitarbeiter) template.get(Mitarbeiter.class, mitarbeiterId);
		Verleih f = new Verleih();
		f.setCreated(new Date());
		f.setVon(new Date());
		f.setAuto(a);
		f.setMitarbeiter(m);
		f.setKilometerstand(kilometerstand);
		try {
			template.saveOrUpdate(f);
		} catch (DataAccessException e) {
			throw new DaoException("Ein und der selbe Fahrer kann nicht zwei Verleihe durchführen.");
		}
	}

	/**
	 * Ends a trip by adding an ankunft date.
	 * @param id
	 */
	public void rueckgeben(int id) {
		HibernateTemplate template = getHibernateTemplate();
		Verleih v = (Verleih) template.get(Verleih.class, id);
		v.setBis(new Date());
		template.saveOrUpdate(v);
	}

	/**
	 * <p>returns all Fahrt objects as FahrtBootPersonDTO objects.</p>
	 * <p>In order to access lazy loaded properties of those, a HibernateCallback is used.</p>
	 * @return A sorted set of FahrtPersonenDTO objects
	 * @see http://static.springframework.org/spring/docs/2.5.x/reference/orm.html#orm-hibernate-template
	 */
//	@SuppressWarnings({ "unchecked", "rawtypes" })
//	public List<FahrtBootPersonDTO> findAllVoll() {
//		HibernateTemplate template = getHibernateTemplate();
//		return (List<FahrtBootPersonDTO>) template.execute(new HibernateCallback() {
//			@Override
//			public Object doInHibernate(Session session) throws HibernateException, SQLException {
//				Criteria criteria = session.createCriteria(Verleih.class);
//				List<Verleih> alleFahrten = criteria.list();
//				List<FahrtBootPersonDTO> liste = new LinkedList<FahrtBootPersonDTO>();
//				for (Verleih f : alleFahrten) {
//					Set<Mitarbeiter> ruderer = f.getRuderer();
//					for (Mitarbeiter p : ruderer) {
//						FahrtBootPersonDTO fbpDto = new FahrtBootPersonDTO(f, p);
//						liste.add(fbpDto);
//					}
//				}
//				return liste;
//			}
//		});
//	}

	@SuppressWarnings("unchecked")
	public Set<Verleih> findByAuto(Auto auto) {
		Session hibernateSession = getSession();
		Criteria crit = hibernateSession.createCriteria(Verleih.class);
		crit.add(Restrictions.eq("auto", auto));
		List<Verleih> tmp = crit.list();
		Set<Verleih> result = new HashSet<Verleih>();
		for (Verleih f : tmp) {
			result.add(f);
		}
		return result;
	}

}
